#ifndef MAPCONTROL_H
#define MAPCONTROL_H

#include <QtCore/QTimer>
#include <QtCore/QCoreApplication>

#include <QtGui/QWidget>
#include <QtGui/QWheelEvent>

#include "layermanager.h"
#include "layer.h"
#include "mapadapter.h"
#include "geometry.h"
#include "imagemanager.h"

class LayerManager;
class MapAdapter;
class Layer;

class MapControl : public QWidget
{
    Q_OBJECT

public:
    enum MouseMode
    {
        Panning, /*!< The map is moved */
        Dragging, /*!< A rectangular can be drawn */
        None /*!< Mouse move events have no efect to the map */
    };

    MapControl ( QSize size, MouseMode mousemode = Panning, QWidget* parent=0 );

    virtual ~MapControl();

    void addLayer ( Layer* layer );

    Layer* layer ( const QString& layername ) const;

    QList<QString> layers() const;

    int numberOfLayers() const;

    QPointF	currentCoordinate() const;

    int zoom() const;

    void setView ( const QPointF& coordinate ) const;

    void setView ( const QList<QPointF> coordinates ) const;

    void setViewAndZoomIn ( const QList<QPointF> coordinates ) const;

    void setView ( const Point* point ) const;

    void followGeometry ( const Geometry* geometry ) const;

    void stopFollowing ( Geometry* geometry );

    void moveTo	( QPointF coordinate );

    void setMouseMode ( MouseMode mousemode );

    MapControl::MouseMode mouseMode();

    //int rotation;

    void enablePersistentCache ( const QDir& path=QDir::homePath() + "/QMapControl.cache" );


    void setProxy ( QString host, int port );

    void showScale ( bool show );

    virtual void resize(int w, int h);

private:
    LayerManager* layermanager;
    ImageManager* imagemanager;
    QPoint screen_middle;         // middle of the widget (half size)

    QPoint pre_click_px;          // used for scrolling (MouseMode Panning)
    QPoint current_mouse_pos;     // used for scrolling and dragging (MouseMode Panning/Dragging)

    QSize size;                   // size of the widget

    bool mousepressed;
    MouseMode mymousemode;
    bool scaleVisible;

    bool m_loadingFlag;

    QMutex moveMutex;             // used for method moveTo()
    QPointF target;               // used for method moveTo()
    int steps;                    // used for method moveTo()

    QPointF clickToWorldCoordinate ( QPoint click );
    MapControl& operator= ( const MapControl& rhs );
    MapControl ( const MapControl& old );

    void drawScale(QPainter& painter);
    void drawMiddlePlus(QPainter& painter);
    void drawBoundRect(QPainter& painter);

private:
    QList<Layer*> m_layers;

protected:
    void paintEvent ( QPaintEvent* evnt );
    void mousePressEvent ( QMouseEvent* evnt );
    void mouseReleaseEvent ( QMouseEvent* evnt );
    void mouseMoveEvent ( QMouseEvent* evnt );
    void wheelEvent(QWheelEvent *);

signals:
    // void mouseEvent(const QMouseEvent* evnt);

    void mouseEventCoordinate ( const QMouseEvent* evnt, const QPointF coordinate );

    void boxDragged ( const QRectF );

    void geometryClicked ( Geometry* geometry, QPoint coord_px );

    void viewChanged ( const QPointF &coordinate, int zoom );

public slots:
    void zoomIn();

    void zoomOut();

    void setZoom ( int zoomlevel );

    void scrollLeft ( int pixel=10 );

    void scrollRight ( int pixel=10 );

    void scrollUp ( int pixel=10 );

    void scrollDown ( int pixel=10 );

    void scroll ( const QPoint scroll );

    void updateRequest ( QRect rect );

    void updateRequestNew();

    void resize(const QSize newSize);

private slots:
    void tick();
    void loadingFinished();
    void positionChanged ( Geometry* geom );
};

#endif
